﻿using Biotech.Log;
using MaterialDesignThemes.Wpf;
using Microsoft.Expression.Drawing.Core;
using Microsoft.Win32;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using OfficeOpenXml;
using project.B12.application.Ioc;
using project.B12.application.ViewModels.Dialogs;
using project.B12.application.Views.Dialogs;
using project.B12.IRepository;
using project.B12.IService;
using project.B12.Model.Models;
using project.B12.Model.Res;
using project.B12.Repository.Repository;
using project.B12.Service;
using project.B12.ViewModels;
using software.Common.MVVM;
using Software.Common.Util.AppConfig;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using ICell = NPOI.SS.UserModel.ICell;

namespace project.B12.application.ViewModels.Setting
{
    public class DeviceSettingViewModel : ObservableObject
    {
        private IMICPlateMes _mICPlateMes;
        private PublicResourceViewModel _publicResourceViewModel;
        private IBacteriaRepository _bacteriaRepository;
        public IServiceDevice serviceDevce { get; set; }

        #region Model
        private int _columnIndex;
        private int _rowIndex;

        private List<ProjectRule> projectRules {  get; set; }
        public List<ProjectRule> ProjectRules
        {
            get { return projectRules; }
            set
            {
                projectRules = value;
                this.RaisePropertyChanged();
            }
        }

        private List<string> _volumes { get; set; }
        public List<string> Volumes
        {
            get { return _volumes; }
            set
            {
                _volumes = value;
                this.RaisePropertyChanged();
            }
        }

        private string volume {  get; set; }
        public string Volume
        {
            get { return volume; }
            set
            {
                volume = value;
                this.RaisePropertyChanged();
            }
        }

        private string _projectName { get; set; }
        public string ProjectName
        {
            get { return _projectName; }
            set
            {
                _projectName = value;
                this.RaisePropertyChanged();
            }
        }

        private string _projectFile { get; set; }
        public string ProjectFile
        {
            get { return _projectFile; }
            set
            {
                _projectFile = value;
                this.RaisePropertyChanged();
            }
        }

        private string _temperature { get; set; }
        public string Temperature
        {
            get { return _temperature; }
            set
            {
                _temperature = value;
                this.RaisePropertyChanged();
            }
        }

        private bool isVertical;
        /// <summary>
        /// 是否竖向
        /// </summary>
        public bool IsVertical
        {
            get { return isVertical; }
            set
            {
                isVertical = value;
                this.RaisePropertyChanged();
            }
        }

        private string currentPhotoInterval;
        public string CurrentPhotoInterval
        {
            get { return currentPhotoInterval; }
            set
            {
                currentPhotoInterval = value;
                this.RaisePropertyChanged();
            }
        }

        private string photoInterval;
        /// <summary>
        /// 拍照间隔时间
        /// </summary>
        public string PhotoInterval
        {
            get { return photoInterval; }
            set
            {
                photoInterval = value;
                this.RaisePropertyChanged();
            }
        }

        private bool isRule1;
        public bool IsRule1
        {
            get { return isRule1; }
            set
            {
                isRule1 = value;
                this.RaisePropertyChanged();
            }
        }

        private string sampleType;
        public string SampleType
        {
            get { return sampleType; }
            set
            {
                sampleType = value;
                this.RaisePropertyChanged();
            }
        }

        private string sampleInput;
        public string SampleInput
        {
            get { return sampleInput; }
            set
            {
                sampleInput = value;
                SampleTypes = _publicResourceViewModel.BacteriaNames.Where(o => o.Contains(value)).ToList();
                if (string.IsNullOrEmpty(value))
                    SampleType = null;
                this.RaisePropertyChanged();
            }
        }

        private List<string> sampleTypes;
        public List<string> SampleTypes
        {
            get { return sampleTypes; }
            set
            {
                sampleTypes = value;
                this.RaisePropertyChanged();
            }
        }
        #endregion

        #region Command
        public RelayCommand Import => new RelayCommand(ImportExcel);
        public RelayCommand SaveProject => new RelayCommand(SaveProjectExcel);
        public RelayCommand<object> Update1=>new RelayCommand<object>((str)=>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule,1);
        });
        public RelayCommand<object> Update2 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 2);
        });
        public RelayCommand<object> Update3 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 3);
        });
        public RelayCommand<object> Update4 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 4);
        });
        public RelayCommand<object> Update5 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 5);
        });
        public RelayCommand<object> Update6 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 6);
        });
        public RelayCommand<object> Update7 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 7);
        });
        public RelayCommand<object> Update8 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 8);
        });
        public RelayCommand<object> Update9 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 9);
        });
        public RelayCommand<object> Update10 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 10);
        });
        public RelayCommand<object> Update11 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 11);
        });
        public RelayCommand<object> Update12 => new RelayCommand<object>((str) =>
        {
            var projectRule = str as ProjectRule;
            UpdatePreject(projectRule, 12);
        });
        public RelayCommand TemSetting => new RelayCommand(SetTemperature);
        public RelayCommand PhotoIntervalSetting => new RelayCommand(SetPhotoInterval);
        public RelayCommand CancelIntervalSetting => new RelayCommand(CancelInterval);
        public RelayCommand Clear => new RelayCommand(ClearProjectRules);
        public RelayCommand Add => new RelayCommand(() =>
        {
            if (string.IsNullOrEmpty(SampleType))
                return;
            _publicResourceViewModel.RecordBacterias.Add(SampleType);
            MessageBox.Show("添加成功");
        });
        #endregion

        public DeviceSettingViewModel(IMICPlateMes mICPlateMes,IServiceDevice serviceDevice, IBacteriaRepository bacteriaRepository) 
        {
            serviceDevce=serviceDevice;
            _mICPlateMes = mICPlateMes;
            _bacteriaRepository=bacteriaRepository;
            _publicResourceViewModel =ViewModelLocator.PublicResourceViewModel;

            if (UtilAppConfig.ExistItem("PhotoInterval"))
                CurrentPhotoInterval = UtilAppConfig.GetAppConfig("PhotoInterval");

            Volumes = new List<string>() ;
            Volumes.Add("50");
            Volumes.Add("100");
            Volumes.Add("150");
            Volumes.Add("200");
            Volumes.Add("250");
            InitProjectRules();
            Volume = Volumes[0];
            IsRule1 = true;
            var bacterias = bacteriaRepository.QueryAllBacteria();
            SampleTypes = new List<string>();
            foreach (var bacteria in bacterias)
            {
                SampleTypes.Add(bacteria.CN_Name);
            }
        }

        private void InitProjectRules()
        {
            ProjectRules = new List<ProjectRule>();
            for (int i = 0; i < 8; i++)
            {
                ProjectRule rule = new ProjectRule();
                rule.Drugs = new ObservableCollection<string>();
                rule.Concentrations = new ObservableCollection<string>();
                for (int j = 0; j < 12; j++)
                {
                    rule.Drugs.Add("");
                    rule.Concentrations.Add("");
                }
                rule.RowName = Convert.ToChar(i + 65).ToString();
                ProjectRules.Add(rule);
            }
        }

        private void ImportExcel()
        {
            try
            {
                if (!Directory.Exists("conf"))
                    throw new Exception($"Directory 'conf' not found.文件缺失或异常");
                string path = AppDomain.CurrentDomain.BaseDirectory + @"conf";
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.InitialDirectory = path;
                openFileDialog.Title = "选择一个文件";
                openFileDialog.Filter = "Excel工作表(*.xlsx)|*.xlsx";

                if (openFileDialog.ShowDialog() == true)
                {
                    int index = openFileDialog.FileName.LastIndexOf("\\");
                    ProjectFile = openFileDialog.FileName.Substring(index + 1);
                    ProjectName = openFileDialog.FileName.Substring(index + 1).Split('.')[0];
                }
                else
                    return;

                ReadExcel(openFileDialog.FileName);
            }
            catch { };
        }

        private void ReadExcel(string filePath)
        {
            ProjectRules = new List<ProjectRule>();
            FileStream fs=null;
            IWorkbook workbook=null;
            ISheet sheet=null;
            DataTable dataTable = null;
            ICell cell = null;
            DataColumn column = null;
            DataRow dataRow = null;
            bool excelEnd = false;
            try
            {
                using (fs = File.OpenRead(filePath))
                {
                    // 2007版本  
                    if (filePath.IndexOf(".xlsx") > 0)
                        workbook = new XSSFWorkbook(fs);
                    // 2003版本  
                    else if (filePath.IndexOf(".xls") > 0)
                        workbook = new HSSFWorkbook(fs);

                    sheet = workbook.GetSheetAt(0); 
                    dataTable = new DataTable();
                    if (sheet != null)
                    {
                        int rowCount = sheet.LastRowNum;//总行数
                        if (rowCount <= 0)
                        {
                            WPF.Controls.Message.Push("该表内容为空！",System.Windows.MessageBoxImage.Warning);
                            return ;
                        }
                        IRow firstRow = sheet.GetRow(0);//第一行  
                        int cellCount = firstRow.LastCellNum;//列数  
                        for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
                        {
                            cell = firstRow.GetCell(i);
                            if (cell != null)
                            {
                                switch (cell.CellType)
                                {
                                    case CellType.Blank:
                                        dataTable.Columns.Add("");
                                        break;
                                    case CellType.Numeric:
                                        short format = cell.CellStyle.DataFormat;
                                        if (format == 14 || format == 31 || format == 57 || format == 58)
                                            dataTable.Columns.Add(cell.DateCellValue.ToString());
                                        else
                                            dataTable.Columns.Add(cell.NumericCellValue.ToString());
                                        break;
                                    case CellType.String:
                                        dataTable.Columns.Add(cell.StringCellValue);
                                        break;
                                }
                            }
                        }

                        for (int i = 1; i <= rowCount; i++)
                        {
                            if(excelEnd)
                            {
                                Volume = sheet.GetRow(i + 2).GetCell(4).ToString();
                                break;
                            }
                            IRow row = null;
                            row = sheet.GetRow(i);
                            if (row == null) 
                                break;
                            dataRow = dataTable.NewRow();
                            ProjectRule rule= new ProjectRule();
                            rule.RowName = Convert.ToChar(i + 64).ToString();
                            rule.Drugs = new ObservableCollection<string>();
                            rule.Concentrations=new ObservableCollection<string>();
                            for (int j = row.FirstCellNum+1; j < cellCount; ++j)
                            {
                                cell = row.GetCell(j);
                                if (cell == null)
                                {
                                    dataRow[j] = "";
                                }
                                else
                                { 
                                    switch (cell.CellType)
                                    {
                                        case CellType.Blank:
                                            dataRow[j] = "";
                                            break;
                                        case CellType.Numeric:
                                            short format = cell.CellStyle.DataFormat;
                                            //对时间格式（2015.12.5、2015/12/5、2015-12-5等）的处理  
                                            if (format == 14 || format == 31 || format == 57 || format == 58)
                                                dataRow[j] = cell.DateCellValue;
                                            else
                                                dataRow[j] = cell.NumericCellValue;
                                            break;
                                        case CellType.String:
                                            dataRow[j] = cell.StringCellValue;
                                            break;
                                    }
                                }
                                string[] temp = new string[2];
                                if (dataRow[j].ToString().Contains(","))
                                    temp = dataRow[j].ToString().Split(",");
                                else
                                {
                                    temp[0] = dataRow[j].ToString();
                                    temp[1] = string.Empty;
                                }
                                rule.Drugs.Add(temp[0]);
                                rule.Concentrations.Add(temp[1]);

                                if (i==8)
                                    excelEnd=true;
                            }
                            ProjectRules.Add(rule);
                            dataTable.Rows.Add(dataRow);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (fs != null)
                {
                    WPF.Controls.Message.Push("导入失败！");
                    LoggerFactory.Instance.CurrentLogger.LogInfo($"{filePath}导入失败\n"+ex.ToString(), "", "软件");
                    fs.Close();
                }
            }
            Random random = new Random();
            int index = random.Next(0, 7);
            for (int i = 0; i < ProjectRules[index].Drugs.Count - 1; i++)
            {
                if (ProjectRules[index].Drugs[i] != ProjectRules[index].Drugs[i + 1])
                {
                    IsVertical = true;
                    break;
                }
                IsVertical = false;
            }
        }

        private void SaveProjectExcel()
        {
            try
            {
                //if (!CheckDataArrangement(ProjectRules,IsVertical))
                //    return;

                string templatePath = AppDomain.CurrentDomain.BaseDirectory + @"模版.xlsx";
                if(!File.Exists(templatePath))
                {
                    WPF.Controls.Message.Push("模版不存在", MessageBoxImage.Warning);
                    return;
                }

                string path = AppDomain.CurrentDomain.BaseDirectory + @"conf";
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Title = "选择一个文件";
                saveFileDialog.InitialDirectory = path;
                saveFileDialog.Filter = "Excel 文件(*.xlsx)|*.xlsx";
                if (saveFileDialog.ShowDialog() == false)
                    return;

                ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
                FileInfo templateFile=new FileInfo(templatePath);
                FileInfo outFile = new FileInfo(saveFileDialog.FileName);
                string projectName = null;
                using (var package = new ExcelPackage(templateFile))
                {
                    var worksheet = package.Workbook.Worksheets[0];
                    int index = saveFileDialog.FileName.LastIndexOf("\\");
                    projectName = saveFileDialog.FileName.Substring(index + 1).Split('.')[0];
                    worksheet.Cells[1, 1].Value = projectName;
                    //添加表头
                    //for (int i = 2; i <= 13; i++)
                    //{
                    //    worksheet.Cells[1, i].Value = i - 1;
                    //}

                    //添加数据
                    for (int i = 2; i <= 9; i++)
                    {
                        worksheet.Cells[i, 1].Value = ProjectRules[i - 2].RowName;
                        for (int j = 2; j <= 13; j++)
                        {
                            string value = ProjectRules[i - 2].Drugs[j - 2];
                            if (!string.IsNullOrEmpty(ProjectRules[i - 2].Concentrations[j - 2]))
                                value = value + "," + ProjectRules[i - 2].Concentrations[j - 2];

                            worksheet.Cells[i, j].Value = value;
                        }
                    }
                    //worksheet.Cells[10, 1].Value = "name:";
                    //worksheet.Cells[10, 4].Value = "type:";
                    //worksheet.Cells[10, 5].Value = 1.ToString();
                    //worksheet.Cells[11, 4].Value = "map:";
                    //worksheet.Cells[11, 5].Value = 1.ToString();
                    //worksheet.Cells[12, 4].Value = "volume";
                    worksheet.Cells[12, 5].Value = Volume;
                    package.SaveAs(outFile);
                    _mICPlateMes.Init();
                    ProjectFile = saveFileDialog.FileName.Substring(index + 1);
                    MessageBox.Show(Resources.ExportSuccess);
                };

            }
            catch (Exception ex)
            {
                LoggerFactory.Instance.CurrentLogger.LogInfo("导出失败\n" + ex.ToString(), "", "软件");
            };
        }

        private bool CheckDataArrangement(List<ProjectRule> rules,bool isVertical)
        {
            if(isVertical)
            {
                for(int j=0;j<8;j++)
                {
                    for (int i = 0; i < 11; i++)
                    {
                        if (rules[j].Drugs[i] == rules[j].Drugs[i+1])
                        {
                            MessageBoxResult result = MessageBox.Show($"第{i + 1}列药物与第{j + 1}行药物一致，是否继续保存？", 
                                "提示", MessageBoxButton.OKCancel, MessageBoxImage.Question);
                            if (result == MessageBoxResult.Cancel)
                                return false;
                            else
                                return true;
                        }
                    }
                }
            }
            else
            {
                for(int i=0;i<12;i++)
                {
                    for(int j=0;j<7;j++)
                    {
                        if (string.IsNullOrEmpty(rules[j].Drugs[i]))
                            continue;

                        if (rules[j].Drugs[i] == rules[j+1].Drugs[i])
                        {
                            {
                                MessageBoxResult result = MessageBox.Show($"第{i + 1}列药物与第{j + 1}行药物一致，是否继续保存？",
                                    "提示", MessageBoxButton.OKCancel, MessageBoxImage.Question);
                                if (result == MessageBoxResult.Cancel)
                                    return false;
                                else
                                    return true;
                            }
                        }
                    }
                }
            }
            return true;
        }

        private void UpdatePreject(ProjectRule rule,int index)
        {
            ProjectRuleSettingViewModel vm = ViewModelLocator.ProjectRuleSettingViewModel;
            //传值
            vm.MedicineName = rule.Drugs[index-1];
            vm.MaxConcentration = rule.Concentrations[index - 1];
            for (int i = 'H'- rule.RowName[0]+1; i >= 1; i--)
            {
                int level = i - 'A';
                vm.VerticalLevels.Add(i.ToString());
            }
            for (int i = 12-index+1; i >= 1; i--)
            {
                vm.HorizontalLevels.Add(i.ToString());
            }
            vm.Vertical=IsVertical;
            vm.Horizontal = !IsVertical;
            _columnIndex = index-1;
            _rowIndex = rule.RowName[0] - 65;
            ProjectRuleSettingView projectRuleSetting = new ProjectRuleSettingView();
            projectRuleSetting.DataContext = vm;
            vm.ReturnPlate -= SetProjectRuleSettingViewModel;
            vm.ReturnPlate += SetProjectRuleSettingViewModel;
            App.Current.Dispatcher.Invoke(() =>
            {
                DialogHost.Show(projectRuleSetting, "Main");
            });
        }

        private void SetProjectRuleSettingViewModel(ProjectRuleSettingViewModel vm)
        {
            if (vm.Positive)
            {
                ProjectRules[_rowIndex].Drugs[_columnIndex] = "+";
                ProjectRules[_rowIndex].Concentrations[_columnIndex] = string.Empty;
            }
            else if (vm.Negative)
            {
                ProjectRules[_rowIndex].Drugs[_columnIndex] = "-";
                ProjectRules[_rowIndex].Concentrations[_columnIndex] = string.Empty;
            }
            else if (vm.IsBatch)
            {
                SetBatchProjectRules(vm);
            }
            else
            {
                ProjectRules[_rowIndex].Drugs[_columnIndex] = vm.ProjectMedicineName.Split(" ")[0];
                ProjectRules[_rowIndex].Concentrations[_columnIndex] = vm.MaxConcentration;

            }
            if (DialogHost.IsDialogOpen("Main"))
                DialogHost.Close("Main", true);
        }

        private void SetBatchProjectRules(ProjectRuleSettingViewModel vm)
        {
            string medicineName = vm.ProjectMedicineName.Split(" ")[0];
            double concentration =double.Parse(vm.MaxConcentration);
            int row = 0;
            int column = 0;
            IsVertical = vm.Vertical;

            if (vm.Vertical)
            {
                for(int i = 0; i < int.Parse(vm.ConcentrationLevel); i++)
                {
                    if (i!=0)
                    {
                        concentration = concentration / 2;
                    }
                    ProjectRules[_rowIndex + i].Drugs[_columnIndex] = medicineName;
                    ProjectRules[_rowIndex + i].Concentrations[_columnIndex] = GetConcentration(concentration);
                }
                row = _rowIndex + int.Parse(vm.ConcentrationLevel) - 1;
                column = _columnIndex;
            }
            else
            {
                for (int i = 0; i < int.Parse(vm.ConcentrationLevel); i++)
                {
                    if (i != 0)
                    {
                        concentration = concentration / 2;
                    }
                    ProjectRules[_rowIndex].Drugs[_columnIndex+i] = medicineName;
                    ProjectRules[_rowIndex].Concentrations[_columnIndex+i] = GetConcentration(concentration);
                }
                row = _rowIndex;
                column = _columnIndex+ int.Parse(vm.ConcentrationLevel) - 1;
            }
        }

        private string GetConcentration(double concentration)
        {
            if (concentration == Math.Floor(concentration))
                return concentration.ToString();

            return Math.Round(concentration,3).ToString("F3");
        }

        private void SetTemperature()
        {
            float temp;
            if(!float.TryParse(Temperature, out temp))
            {
                WPF.Controls.Message.Push("温度输入错误", MessageBoxImage.Warning);
                return;
            }
            else if(temp<30||temp>37)
            {
                WPF.Controls.Message.Push("温度输入错误", MessageBoxImage.Warning);
                return;
            }
            serviceDevce.UpdateTemp(temp);
            UtilAppConfig.UpdateAppConfig("Temperature", temp.ToString("F1"));
            WPF.Controls.Message.Push("修改成功");
        }

        private void SetPhotoInterval()
        {
            int time = 0;
            if(!int.TryParse(PhotoInterval, out time))
            {
                WPF.Controls.Message.Push("时间输入错误", MessageBoxImage.Warning);
                return;
            }
            serviceDevce.IsPhotoInterval = true;
            _publicResourceViewModel.PhotoTime = time;
            CurrentPhotoInterval = PhotoInterval;
            UtilAppConfig.UpdateAppConfig("PhotoInterval", PhotoInterval);
            UtilAppConfig.UpdateAppConfig("IsPhotoInterval", true.ToString());

            MessageBox.Show("设置成功");
        }

        private void CancelInterval()
        {
            serviceDevce.IsPhotoInterval = false;
            _publicResourceViewModel.PhotoTime = 0;
            CurrentPhotoInterval = "0";
            UtilAppConfig.UpdateAppConfig("PhotoInterval", "0");
            UtilAppConfig.UpdateAppConfig("IsPhotoInterval", false.ToString());
            MessageBox.Show("取消成功");
        }

        private void ClearProjectRules()
        {
            InitProjectRules();
        }
    }
}
